package com.codeplatform.service.impl;

import com.codeplatform.entity.CodeRecord;
import com.codeplatform.dto.CodeExecutionRequest;
import com.codeplatform.dto.CodeExecutionResult;
import com.codeplatform.mapper.CodeRecordMapper;
import com.codeplatform.mapper.UserMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.codeplatform.service.CodeRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 代码记录服务实现类
 * 
 * @author CodePlatform
 * @since 2024-01-01
 */
@Slf4j
@Service
@Transactional
public class CodeRecordServiceImpl implements CodeRecordService {

    @Autowired
    private CodeRecordMapper codeRecordMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public CodeRecord saveCodeRecord(CodeExecutionRequest request, CodeExecutionResult result) {
        try {
            CodeRecord record = CodeRecord.builder()
                    .userId(request.getUserId())
                    .title(generateDefaultTitle(request.getLanguage()))
                    .language(request.getLanguage())
                    .code(request.getCode())
                    .inputData(request.getInput())
                    .output(result.getOutput())
                    .errorMessage(result.getError())
                    .executionTime(result.getExecutionTime() != null ? result.getExecutionTime().intValue() : 0)
                    .memoryUsage(result.getMemoryUsage() != null ? result.getMemoryUsage().intValue() : 0)
                    .executionStatus(result.getSuccess() ? 1 : 2)
                    .isPublic(false)
                    .allowEdit(false)
                    .executionCount(1)
                    .viewCount(0)
                    .build();
            
            codeRecordMapper.insert(record);
            return record;
        } catch (Exception e) {
            log.error("保存代码记录失败", e);
            throw new RuntimeException("保存代码记录失败: " + e.getMessage());
        }
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<CodeRecord> getCodeRecord(Long id) {
        CodeRecord record = codeRecordMapper.selectById(id);
        return Optional.ofNullable(record);
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<CodeRecord> getCodeRecord(Long id, Long userId) {
        CodeRecord record = codeRecordMapper.selectById(id);
        if (record != null && record.canAccess(userId)) {
            return Optional.of(record);
        }
        return Optional.empty();
    }

    @Override
    @Transactional(readOnly = true)
    public Optional<CodeRecord> getCodeRecordByShareToken(String shareToken) {
        CodeRecord record = codeRecordMapper.findByShareToken(shareToken);
        return Optional.ofNullable(record);
    }

    @Override
    @Transactional(readOnly = true)
    public IPage<CodeRecord> getUserCodeRecords(Long userId, Page<CodeRecord> page) {
        return codeRecordMapper.getUserCodeRecords(userId, page);
    }
    
    @Override
    @Transactional(readOnly = true)
    public List<CodeRecord> getUserCodeRecords(Long userId, int page, int size, String language) {
        try {
            Page<CodeRecord> pageObj = new Page<>(page + 1, size); // MyBatis-Plus页码从1开始
            IPage<CodeRecord> result;
            
            if (language != null && !language.trim().isEmpty()) {
                result = codeRecordMapper.getUserCodeRecordsByLanguage(userId, language, pageObj);
            } else {
                result = codeRecordMapper.getUserCodeRecords(userId, pageObj);
            }
            
            return result.getRecords();
        } catch (Exception e) {
            log.error("获取用户代码记录失败，用户ID: {}, 页码: {}, 大小: {}, 语言: {}", userId, page, size, language, e);
            return new ArrayList<>();
        }
    }
    
    @Override
    @Transactional(readOnly = true)
    public long getUserCodeRecordCount(Long userId, String language) {
        try {
            if (language != null && !language.trim().isEmpty()) {
                return codeRecordMapper.getUserCodeRecordCountByLanguage(userId, language);
            } else {
                return codeRecordMapper.getUserCodeRecordCount(userId);
            }
        } catch (Exception e) {
            log.error("获取用户代码记录总数失败，用户ID: {}, 语言: {}", userId, language, e);
            return 0;
        }
    }

    @Override
    @Transactional(readOnly = true)
    public IPage<CodeRecord> getUserCodeRecordsByLanguage(Long userId, String language, Page<CodeRecord> page) {
        return codeRecordMapper.findByUserIdAndLanguageOrderByCreatedAtDesc(page, userId, language);
    }

    @Override
    @Transactional(readOnly = true)
    public IPage<CodeRecord> searchUserCodeRecords(Long userId, String keyword, Page<CodeRecord> page) {
        return codeRecordMapper.findByUserIdAndTitleContainingIgnoreCaseOrderByCreatedAtDesc(page, userId, keyword);
    }

    @Override
    @Transactional(readOnly = true)
    public IPage<CodeRecord> getPublicCodeRecords(Page<CodeRecord> page) {
        return codeRecordMapper.findByIsPublicTrueOrderByCreatedAtDesc(page);
    }

    @Override
    @Transactional(readOnly = true)
    public IPage<CodeRecord> getPublicCodeRecordsByLanguage(String language, Page<CodeRecord> page) {
        return codeRecordMapper.findByLanguageAndIsPublicTrueOrderByCreatedAtDesc(page, language);
    }

    @Override
    @Transactional(readOnly = true)
    public IPage<CodeRecord> getPopularCodeRecords(Page<CodeRecord> page) {
        return codeRecordMapper.findByIsPublicTrueOrderByViewCountDescCreatedAtDesc(page);
    }

    @Override
    public Optional<CodeRecord> updateCodeRecord(Long id, String title, String code, Long userId) {
        CodeRecord record = codeRecordMapper.selectById(id);
        if (record != null) {
            if (record.canEdit(userId)) {
                record.setTitle(title);
                record.setCode(code);
                codeRecordMapper.updateById(record);
                log.info("代码记录更新成功，ID: {}, 用户: {}", id, userId);
                return Optional.of(record);
            } else {
                log.warn("用户 {} 无权限编辑代码记录 {}", userId, id);
            }
        }
        return Optional.empty();
    }

    @Override
    public boolean deleteCodeRecord(Long id, Long userId) {
        CodeRecord record = codeRecordMapper.selectById(id);
        if (record != null) {
            if (record.isOwner(userId)) {
                codeRecordMapper.deleteById(id);
                log.info("代码记录删除成功，ID: {}, 用户: {}", id, userId);
                return true;
            } else {
                log.warn("用户 {} 无权限删除代码记录 {}", userId, id);
            }
        }
        return false;
    }

    @Override
    public String shareCodeRecord(Long id, boolean isPublic, boolean allowEdit, Long userId) {
        CodeRecord record = codeRecordMapper.selectById(id);
        if (record != null) {
            if (record.isOwner(userId)) {
                String shareToken = generateShareToken();
                record.setIsPublic(isPublic);
                record.setAllowEdit(allowEdit);
                record.setShareToken(shareToken);
                record.setSharedAt(LocalDateTime.now());
                codeRecordMapper.updateById(record);
                log.info("代码记录分享成功，ID: {}, 用户: {}, 分享令牌: {}", id, userId, shareToken);
                return shareToken;
            } else {
                log.warn("用户 {} 无权限分享代码记录 {}", userId, id);
            }
        }
        return null;
    }

    @Override
    public boolean unshareCodeRecord(Long id, Long userId) {
        CodeRecord record = codeRecordMapper.selectById(id);
        if (record != null) {
            if (record.isOwner(userId)) {
                record.setIsPublic(false);
                record.setAllowEdit(false);
                record.setShareToken(null);
                record.setSharedAt(null);
                codeRecordMapper.updateById(record);
                log.info("代码记录取消分享成功，ID: {}, 用户: {}", id, userId);
                return true;
            } else {
                log.warn("用户 {} 无权限取消分享代码记录 {}", userId, id);
            }
        }
        return false;
    }

    @Override
    public void incrementViewCount(Long id) {
        CodeRecord record = codeRecordMapper.selectById(id);
        if (record != null) {
            record.incrementViewCount();
            codeRecordMapper.updateById(record);
        }
    }

    @Override
    public void incrementExecutionCount(Long id) {
        CodeRecord record = codeRecordMapper.selectById(id);
        if (record != null) {
            record.incrementExecutionCount();
            codeRecordMapper.updateById(record);
        }
    }

    @Override
    @Transactional(readOnly = true)
    public UserCodeStatistics getUserStatistics(Long userId) {
        UserCodeStatistics statistics = new UserCodeStatistics();
        
        // 总记录数
        statistics.setTotalRecords(codeRecordMapper.countByUserId(userId));
        
        // 总执行次数
        Long totalExecutions = codeRecordMapper.sumExecutionCountByUserId(userId);
        statistics.setTotalExecutions(totalExecutions != null ? totalExecutions : 0L);
        
        // 总查看次数
        Long totalViews = codeRecordMapper.sumViewCountByUserId(userId);
        statistics.setTotalViews(totalViews != null ? totalViews : 0L);
        
        // 最常用语言
        List<String> languages = codeRecordMapper.findMostUsedLanguagesByUser(userId);
        if (!languages.isEmpty()) {
            statistics.setMostUsedLanguage(languages.get(0));
        }
        
        // 最后活动时间
        List<CodeRecord> recentRecords = codeRecordMapper.findRecentByUserId(userId, 1);
        if (!recentRecords.isEmpty()) {
            statistics.setLastActivity(recentRecords.get(0).getUpdatedAt());
        }
        
        // 语言分布
        Map<String, Long> languageDistribution = new HashMap<>();
        List<Object[]> languageStats = codeRecordMapper.findLanguageStatistics();
        for (Object[] stat : languageStats) {
            languageDistribution.put((String) stat[0], (Long) stat[1]);
        }
        statistics.setLanguageDistribution(languageDistribution);
        
        return statistics;
    }

    @Override
    @Transactional(readOnly = true)
    public SystemCodeStatistics getSystemStatistics() {
        SystemCodeStatistics statistics = new SystemCodeStatistics();
        
        // 总记录数
        statistics.setTotalRecords(codeRecordMapper.selectCount(null));
        
        // 总用户数
        statistics.setTotalUsers(userMapper.selectCount(null));
        
        // 今日执行次数
        LocalDateTime startOfDay = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime endOfDay = startOfDay.plusDays(1);
        Long todayExecutions = codeRecordMapper.countExecutionsByTimeRange(startOfDay, endOfDay);
        statistics.setTodayExecutions(todayExecutions != null ? todayExecutions : 0L);
        
        // 最受欢迎的语言
        List<Object[]> languageStats = codeRecordMapper.findLanguageStatistics();
        if (!languageStats.isEmpty()) {
            statistics.setMostPopularLanguage((String) languageStats.get(0)[0]);
        }
        
        return statistics;
    }

    @Override
    @Transactional(readOnly = true)
    public List<LanguageStatistics> getLanguageStatistics() {
        List<Object[]> stats = codeRecordMapper.findLanguageStatistics();
        long totalRecords = codeRecordMapper.selectCount(null);
        
        return stats.stream()
                .map(stat -> {
                    String language = (String) stat[0];
                    Long count = (Long) stat[1];
                    LanguageStatistics langStat = new LanguageStatistics(language, count);
                    if (totalRecords > 0) {
                        langStat.setPercentage((double) count / totalRecords * 100);
                    }
                    return langStat;
                })
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(readOnly = true)
    public List<CodeRecord> getRecentCodeRecords(Long userId, int limit) {
        return codeRecordMapper.findRecentByUserId(userId, limit);
    }

    @Override
    public int cleanupExpiredSharedRecords(int expireDays) {
        LocalDateTime expireTime = LocalDateTime.now().minusDays(expireDays);
        List<CodeRecord> expiredRecords = codeRecordMapper.findExpiredSharedRecords(expireTime);
        
        int cleanedCount = 0;
        for (CodeRecord record : expiredRecords) {
            record.setShareToken(null);
            record.setSharedAt(null);
            record.setIsPublic(false);
            record.setAllowEdit(false);
            codeRecordMapper.updateById(record);
            cleanedCount++;
        }
        
        log.info("清理过期分享记录完成，清理数量: {}", cleanedCount);
        return cleanedCount;
    }

    /**
     * 生成默认标题
     */
    private String generateDefaultTitle(String language) {
        return language + " 代码片段 - " + LocalDateTime.now().toString().substring(0, 19);
    }

    /**
     * 生成分享令牌
     */
    private String generateShareToken() {
        return UUID.randomUUID().toString().replace("-", "");
    }
}